<?php

namespace app\index\controller;

use app\admin\controller\Manage;
use think\Cache;
use think\Controller;
use think\Db;
use think\Loader;
use think\Request;
use think\Session;
use think\Validate;
use tree\Tree;

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverKeys;
use Facebook\WebDriver\Remote\RemoteConnection;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\Chrome\ChromeOptions;

class Ai extends Controller
{
    // 启动chromeDriver
    function startChromeDriver()
    {
        return startChromeDriver();
    }

    // 启动$chromeDriver
    function startSeleniumWebDriver()
    {
        return startSeleniumWebDriver();
    }

    /**
     * 一键答题
     * */
    /*public function allExec($file = '')
    {
        if (!$file) {
            $input = Request()->param();

            $question_id = $input['id'];

            if (empty($question_id)) apiReturn(2, '题目ID缺失');

            $message_list = Db::name('message m')->join('auto_plan p', 'm.plan_id = p.id')
                ->field('m.id,m.text,p.answer_count,p.complete_count')
                ->where(['p.question_id' => $question_id, 'p.is_del' => 0])
                ->order('p.id asc')
                ->select();

            $url = Db::name('question')->where(['id' => $question_id])->value('url');
            if (!$url) apiReturn(2, '题目链接缺失');

            $list = processArray($message_list);
            $time = time();
            $file = 'allExec' . $time;
            file_put_contents(RUNTIME_PATH . $file . '.json', json_encode($list, JSON_UNESCAPED_UNICODE));

        }

        // 你的 CMD 命令
        $command = 'start chrome.exe "http://106.14.75.184/index/Ai/allAuto/file/' . $file . '"'; // 替换为你想要执行的命令
        $output = [];
        $return_var = 0;

        // 执行命令
        exec($command, $output, $return_var);
    }*/

    public function allExec()
    {
        $input = Request()->param();

        $question_id = $input['id'];

        if (empty($question_id)) apiReturn(2, '题目ID缺失');

        $time = time();

        Db::startTrans();
        try {
            $all_data = [
                'status' => 1,
                'status_time' => $time
            ];
            Db::name('plan')
                ->where(['question_id' => $question_id, 'is_del' => 0])
                ->where(function ($query) {
                    $query->where('status', 0) // 如果 status 为 0，不加 complete_count < answer_count 条件
                    ->whereOr(function ($query) {
                        $query->where('status', 3)
                            ->where('complete_count', '<', Db::raw('answer_count')); // 如果 status 为 3，添加 complete_count < answer_count
                    });
                })
                ->update($all_data);


            $running_info = Db::name('plan')->where(['status' => 2, 'is_del' => 0])->find();
            if (!$running_info) {
                $run_plan_id = Db::name('plan')->where(['question_id' => $question_id, 'status' => 1, 'is_del' => 0])->min('id');

                if ($run_plan_id) {
                    Db::name('plan')->where(['id' => $run_plan_id])->setField('status', 2);

                    $question_data = [
                        'status' => 2,
                        'status_time' => $time
                    ];

//                    $command = 'start chrome.exe "http://106.14.75.184/index/Ai/auto/plan_id/' . $run_plan_id . '"';
                    $command = 'start chrome.exe "http://www.autoAnswer.com/index/Ai/auto/plan_id/' . $run_plan_id . '"';
                    exec($command);
                } else {
                    Db::rollback();
                    apiReturn(2, '一键答题执行失败');
                }
            } else {
                $question_data = [
                    'status' => 1,
                    'status_time' => $time
                ];
            }

            Db::name('question')->where(['id' => $question_id])->update($question_data);

            Db::commit();
            apiReturn(1, '一键答题执行成功');
        } catch (\Exception $e) {
            Db::rollback();
            apiReturn(2, '一键答题执行失败');
        }
    }

    public function allAuto()
    {
        // 配置 Selenium 服务器 URL
//        $host = 'http://172.20.35.62:4444/wd/hub';     // Selenium Server 地址
        $host = 'http://127.0.0.1:4444/wd/hub';     // Selenium Server 地址
        $capabilities = DesiredCapabilities::chrome(); // 使用 ChromeDriver

        // 初始化 WebDriver
        $driver = RemoteWebDriver::create($host, $capabilities);

        $file = Request()->param('file');

        $list = json_decode(file_get_contents(RUNTIME_PATH . $file . '.json'), true);
        if ($list) {
            foreach ($list as $k => &$v) {
                $message_id = $v['id'];

                $plan_id = Db::name('message')->where(['id' => $message_id])->value('plan_id');


                if (empty($plan_id)) $driver->quit();

                $url = Db::name('question q')->join('auto_plan p', 'q.id = p.question_id')->where(['p.id' => $plan_id, 'q.is_del' => 0])->value('q.url');
                if (!$url) $driver->quit();

                // 打开问卷调查页面
                $driver->get($url);

                // 等待页面加载完成
                $driver->wait()->until(
                    WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('divContent'))
                );

                $plan = Db::name('plan')->where('id', $plan_id)->find();

                $question_rule = json_decode($plan['question_rule'], true);
                if (empty($plan) || empty($question_rule)) $driver->quit();

                $single_answer_time = $question_rule['single_answer_time'];
                // 随机浮动时间 ±5 秒，并计算总时长
                $total_time = $single_answer_time + rand(-5, 0);
                if ($total_time < 5) $driver->quit();

                $answers_list = $v['text'];
                if (!$answers_list) $driver->quit();
                foreach ($answers_list as $key => &$answers) {
                    if (empty($answers)) $driver->quit();

                    // 计算每题的间隔时间，单位微秒（1秒 = 1000000微秒）
                    $num_questions = count($answers);
                    $time_per_question = ($total_time / $num_questions) * 1000000;

                    $this->answerAllQuestions($driver, $answers, $time_per_question);

                    // 提交问卷
                    $submitButton = $driver->findElement(WebDriverBy::id('ctlNext'));
                    $this->scrollToElement($driver, $submitButton); // 滚动到提交按钮
                    $driver->wait()->until(
                        WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::id('ctlNext'))
                    );
                    $driver->executeScript("arguments[0].click();", [$submitButton]);

                    $complete_count = $plan['complete_count'] + 1;
                    Db::name('plan')->where(['id' => $plan_id])->setField('complete_count', $complete_count);

                    unset($answers_list[$key]);

                    $v['complete_count'] = $complete_count;

                    break;
                }

                if ($answers_list) {
                    $list[$k]['text'] = array_values($answers_list);
                } else {
                    unset($list[$k]);
                    $list = array_values($list);
                }

                break;
            }

            file_put_contents(RUNTIME_PATH . $file . '.json', json_encode($list, JSON_UNESCAPED_UNICODE));

            // 关闭 WebDriver
            $driver->quit();

            echo "<script type='text/javascript'>window.close();</script>";

            if ($list) {
                $this->allExec($file);
            } else {
                // 一键答题作答结束
            }
        }
    }

    /*********************   自动刷题 START   ********************/
    /**
     * 单任务答题
     */
    public function exec($plan_id = 0)
    {
        if ($plan_id) {
            $id = $plan_id;

            $now_run = true;// 直接运行命令
        } else {
            $input = Request()->param();
            $id = $input['id'];

            $now_run = false;// 先检查是否有正在运行的任务，再看是否需要直接运行命令
        }

        if (empty($id)) apiReturn(2, '任务ID缺失');

        $info = Db::name('plan')->where(['id' => $id, 'is_del' => 0])->find();
        if (empty($info)) apiReturn(2, '任务不存在或已删除');
        if ($info['answer_count'] <= $info['complete_count']) apiReturn(2, '任务已完成');

        $time = time();
        if ($now_run) {
            if ($info['status'] != 2) {
                $data = [
                    'status' => 2,
                    'status_time' => $time
                ];
                Db::name('plan')->where(['id' => $id])->update($data);

                // 查找正在运行中的问卷
                $search_running_question_info = Db::name('question')->where(['status' => 2])->find();
                if ($search_running_question_info['id'] != $info['question_id']) {
                    // 修改其它问卷状态为1
                    $search_question_data = [
                        'status' => 1,
                        'status_time' => $time
                    ];
                    Db::name('question')->where(['id' => $search_running_question_info['id']])->update($search_question_data);

                    // 修改当前正在运行的问卷状态为2
                    $running_question_data = [
                        'status' => 2,
                        'status_time' => $time
                    ];
                    Db::name('question')->where(['id' => $info['question_id']])->update($running_question_data);
                }
            }

//            $command = 'start chrome.exe "http://106.14.75.184/index/Ai/auto/plan_id/' . $id . '"';
            $command = 'start chrome.exe "http://www.autoAnswer.com/index/Ai/auto/plan_id/' . $id . '"';
            exec($command);
        } else {
            // 查询其他任务正在运行的话，进入排队状态
            $running_count = Db::name('plan')->where(['id' => ['neq', $id], 'status' => 2, 'is_del' => 0])->count();

            $status = $running_count > 0 ? 1 : 2;// 1：自动答题程序已启动，等待答题，2：自动答题程序运行中
            $data = [
                'status' => $status,
                'status_time' => $time
            ];
            $res = Db::name('plan')->where(['id' => $id])->update($data);

            if ($status == 2) {
//                $command = 'start chrome.exe "http://106.14.75.184/index/Ai/auto/plan_id/' . $id . '"';
                $command = 'start chrome.exe "http://www.autoAnswer.com/index/Ai/auto/plan_id/' . $id . '"';
                exec($command);
            }
        }

        if ($res) {
            apiReturn(1, '启动答题程序成功');
        } else {
            apiReturn(2, '启动答题程序失败');
        }
    }

    public function test()
    {
        $ps1FilePath = "D:\\www\\auto_answer\\ai.ps1";

        // 组装命令：使用start命令在后台启动 PowerShell 脚本
        $command = "start /B powershell -ExecutionPolicy Bypass -File \"$ps1FilePath\" -WindowStyle Hidden";
        echo $command;exit;
    }

    public function auto()
    {
        // 配置 Selenium 服务器 URL
//        $host = 'http://172.20.35.62:4444/wd/hub';     // Selenium Server 地址
        $host = 'http://127.0.0.1:4444/wd/hub';     // Selenium Server 地址


        $is_open_rand_ip = C('IS_OPEN_RAND_IP');

        if($is_open_rand_ip){
            $proxy_url = C('PROXY_URL');
            $proxy_port = C('PROXY_PORT');
            if($proxy_url && $proxy_port){
                // 创建代理设置
                $proxy = $proxy_url . ':' . $proxy_port;

                // Chrome 的启动选项
                $options = new \Facebook\WebDriver\Chrome\ChromeOptions();
                $options->addArguments([
                                           "--proxy-server=$proxy", // 设置代理
                                           //                                   "--proxy-auth=$proxyUsername:$proxyPassword" // 代理认证
                                       ]);
                // 启动 Chrome
                $capabilities = DesiredCapabilities::chrome();
                $capabilities->setCapability(\Facebook\WebDriver\Chrome\ChromeOptions::CAPABILITY, $options);
            }else{
                // 启动 Chrome
                $capabilities = DesiredCapabilities::chrome();
            }
        }else{
            // 启动 Chrome
            $capabilities = DesiredCapabilities::chrome();
        }

        // 初始化 WebDriver
        $driver = RemoteWebDriver::create($host, $capabilities);

        $plan_id = Request()->param('plan_id');

        if (empty($plan_id)) $driver->quit();

        $url = Db::name('question q')->join('auto_plan p', 'q.id = p.question_id')->where(['p.id' => $plan_id, 'q.is_del' => 0])->value('url');
        if (!$url) $driver->quit();

        // 打开问卷调查页面
        $driver->get($url);

        // 等待页面加载完成
        $driver->wait()->until(
            WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('divContent'))
        );

        $plan = Db::name('plan')->where('id', $plan_id)->find();

        $question_rule = json_decode($plan['question_rule'], true);
        if (empty($plan) || empty($question_rule)) $driver->quit();

        $single_answer_time = $question_rule['single_answer_time'];
        // 随机浮动时间 ±5 秒，并计算总时长
        $total_time = ($is_open_rand_ip && $proxy_url && $proxy_port)  ? 15 : ($single_answer_time + rand(-5, 0));
        if ($total_time < 5) $driver->quit();

        $text = Db::name('message')->where(['plan_id' => $plan_id])->value('text');
        $text = json_decode($text, true);
        $answers = $text[$plan['complete_count']];

        if (!$text || empty($answers)) $driver->quit();

        // 计算每题的间隔时间，单位微秒（1秒 = 1000000微秒）
        $num_questions = count($answers);
        $time_per_question = ($total_time / $num_questions) * 1000000;

        $this->answerAllQuestions($driver, $answers, $time_per_question);

        // 提交问卷
        $submitButton = $driver->findElement(WebDriverBy::id('ctlNext'));
        $this->scrollToElement($driver, $submitButton); // 滚动到提交按钮
        $driver->wait()->until(
            WebDriverExpectedCondition::elementToBeClickable(WebDriverBy::id('ctlNext'))
        );
        $driver->executeScript("arguments[0].click();", [$submitButton]);

        $complete_count = $plan['complete_count'] + 1;
        Db::name('plan')->where(['id' => $plan_id])->setField('complete_count', $complete_count);

        sleep(1);

        // 关闭 WebDriver
        $driver->quit();

        echo "<script type='text/javascript'>window.close();</script>";

        if ($complete_count < $plan['answer_count']) {
            $this->exec($plan_id);
        } else {
            // 单个任务作答结束，检查是否还有其他问卷处于状态【1：已启动自动答题程序，等待答题】
            $this->endPlanStartOtherPlan($plan_id);
        }
    }

    // 滚动到指定元素并等待其出现
    function scrollToElement($driver, $element)
    {
        $driver->executeScript("arguments[0].scrollIntoView(true);", [$element]);
    }

    // 根据答案选择单选题的选项
    function selectRadio($driver, $divId, $answer)
    {
        $div = $driver->findElement(WebDriverBy::id($divId));
        $this->scrollToElement($driver, $div); // 滚动到当前问题
        $options = $div->findElements(WebDriverBy::tagName('a'));
        if (!empty($options) && isset($options[$answer - 1])) {
            $options[$answer - 1]->click(); // 选择指定选项
        }
    }

    // 根据答案选择多选题的选项
    function selectCheckboxes($driver, $divId, $answers)
    {
        $div = $driver->findElement(WebDriverBy::id($divId));
        $this->scrollToElement($driver, $div); // 滚动到当前问题
        $options = $div->findElements(WebDriverBy::tagName('a'));
        foreach ($answers as $answer) {
            if (isset($options[$answer - 1])) {
                $options[$answer - 1]->click(); // 选择指定选项
            }
        }
    }

    // 输入问答题的答案
    function inputAnswer($driver, $divId, $answer)
    {
        $div = $driver->findElement(WebDriverBy::id($divId));
        $this->scrollToElement($driver, $div); // 滚动到当前问题
        $input = $div->findElement(WebDriverBy::tagName('input'));
        $input->sendKeys($answer); // 输入指定答案
    }

    // 动态处理问卷的所有问题，按顺序回答，并加入时间间隔
    function answerAllQuestions($driver, $answers, $time_per_question)
    {
        $i = 1;
        foreach ($answers as $answer) {
            try {
                $divId = "div" . $i;
                $div = $driver->findElement(WebDriverBy::id($divId));
                $inputs = $div->findElements(WebDriverBy::tagName('input'));
                // 使用 CSS 选择器获取下拉框
                $selects = $div->findElements(WebDriverBy::cssSelector('select'));

                // 判断问题类型
                if (count($selects) > 0) {
                    // 处理下拉框
                    $this->selectDropdown($driver, $divId, $answer);
                } elseif (!empty($inputs)) {
                    // 根据 input 类型判断问题类型
                    $type = $inputs[0]->getAttribute('type');
                    if ($type === 'radio') {
                        $this->selectRadio($driver, $divId, $answer);
                    } elseif ($type === 'checkbox' && is_array($answer)) {
                        $this->selectCheckboxes($driver, $divId, $answer);
                    } elseif ($type === 'text') {
                        $this->inputAnswer($driver, $divId, $answer);
                    }
                }

                $i++;
                usleep($time_per_question);
            } catch (\Exception $e) {
                // 处理异常
            }
        }
    }

    function selectDropdown($driver, $divId, $answer)
    {
        // 打开下拉框
        $driver->executeScript("$('#" . $divId . " select').select2('open');");

        // 等待下拉选项加载
        $driver->wait()->until(
            WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::cssSelector('.select2-results'))
        );

        // 获取所有可选的选项
        $options = $driver->findElements(WebDriverBy::cssSelector('.select2-results__option'));

        // 确保选项存在且 answer 在选项范围内
        if ($answer >= 0 && $answer < count($options)) {
            // 使用 JavaScript 选择选项
            $driver->executeScript("$('#" . $divId . " select').val('" . $answer . "').trigger('change');");
            $driver->executeScript("$('#" . $divId . " select').select2('close');");
        } else {
            throw new Exception("选择的答案超出范围: " . $answer);
        }
    }

    /*********************   自动刷题 END   ********************/


    /**
     * 自动答题程序一个任务结束启动另外一个任务
     * */
    function endPlanStartOtherPlan($plan_id)
    {
        $data = [
            'status' => 3,
            'status_time' => time()
        ];
        Db::name('plan')->where(['id' => $plan_id])->update($data);

        $question_id = Db::name('plan')->where(['id' => $plan_id])->value('question_id');
        // 查询本问卷是否还有【1：自动答题程序已启动，等待答题】的任务
        $question_wait_answer_plan = Db::name('plan')->where(['question_id' => $question_id, 'status' => 1, 'is_del' => 0])->order('status_time asc, id asc')->find();
        if (empty($question_wait_answer_plan)) {
            // 本问卷没有【1：自动答题程序已启动，等待答题】任务，将问卷状态改为【3：自动答题程序已停止】
            $complete_data = [
                'status' => 3,
                'status_time' => time()
            ];
            Db::name('question')->where(['id' => $question_id])->update($complete_data);
        }

        // 查询最新任务
        $wait_answer_plan = Db::name('plan')->where(['status' => 1, 'is_del' => 0])->order('status_time asc, id asc')->find();
        // 其他问卷有【1：自动答题程序已启动，等待答题】任务，启动其他答题任务继续答题
        if ($wait_answer_plan && $wait_answer_plan['id']) $this->exec($wait_answer_plan['id']);
    }

    public function promptToAi($sign, $plan_id, $user_id)
    {
        if (empty($sign)) return false;

        $default_prompt = '我是问卷调查助手，我可以随机帮你生成答案';
        $first_messages = [
            [
                'role' => 'system',
                'content' => $default_prompt
            ]
        ];

        $history_messages = [];
        $info = Db::name('question')->where(['sign' => $sign, 'is_del' => 0])->find();


        $question = json_decode($info['question'], true);

        $new_question = extractOpenEndedQuestions($question);

        $answer_prompt = '关于' . $info['title'] . '的调查问卷，请你回复我一下几个问题：';
        if ($new_question) {
            foreach ($new_question as $k => $v) {
                $answer_prompt .= PHP_EOL . ($k + 1) . '. ' . $v;
            }
        }

        $prompt_template = C('PROMPT_TEMPLATE');// AI提问模板
        $prompt_rule_str = C('PROMPT_RULE');

        $prompt_rule = str_replace("{{ question }}", $answer_prompt, $prompt_template);

        $prompt_rule .= PHP_EOL . $prompt_rule_str;

        $answer_count = Db::name('plan')->where(['id' => $plan_id])->value('answer_count');
        $prompt_rule = str_replace("{{ answer_count }}", $answer_count ? : 1, $prompt_rule);
        $history_messages[] = [
            'role' => 'user',
            'content' => $prompt_rule
        ];

        $messages = array_merge($first_messages, $history_messages);
        $data = textGeneration($messages);
        if ($data === false) {
            // 任务失败
            Db::name('plan')->where(['id' => $plan_id])->setField('is_complete', -1);
            return false;
        } else {
            $text = $data['output']['text'];
            file_put_contents(RUNTIME_PATH . 'AIText.txt', $text . PHP_EOL, FILE_APPEND);

            // 校验-组装数据 START
            $topic_count = countTypeThreeQuestions($question);// 1份问卷中问答题的数量
            $text_arr = json_decode($text, true);
            if (!$text_arr) {
                if (count($text_arr) != $answer_count) {
                    // 尝试重新组装数据

                    $text_arr = assembleSurveyData($text, $topic_count, $answer_count);
                    if (empty($text_arr)) {
                        Db::name('plan')->where(['id' => $plan_id])->setField('is_complete', -1);
                        return false;
                    }
                }
            } else {
                // 校验数据是否合法
                if (!validateSurveyData($text_arr, $topic_count, $answer_count)) {
                    // 尝试重新组装数据
                    $text_arr = assembleSurveyData($text, $topic_count, $answer_count);
                    if (empty($text_arr)) {
                        Db::name('plan')->where(['id' => $plan_id])->setField('is_complete', -1);
                        return false;
                    }
                }
            }
            // 校验-组装数据 END

            $request_id = $data['request_id'];

            if ($text_arr) {
                $user_rule = $info['user_rule'] ? removeEmptyArraysAfterLastNonEmpty(json_decode($info['user_rule'])) : [];

                // 选择题随机答案
                $answers = generateAnswers($question, $answer_count, $user_rule);
                if ($answers) {
                    foreach ($text_arr as $key => $value) {
                        foreach ($value as $v) {
                            $answers[$key][] = $v;
                        }
                    }
                }

                $insert_data = [
                    'user_id' => $user_id,
                    'plan_id' => $plan_id,
                    'sign' => $sign,
                    'prompt' => json_encode($messages, JSON_UNESCAPED_UNICODE),
                    'text' => json_encode($answers, JSON_UNESCAPED_UNICODE),
                    'request_id' => $request_id,
                    'create_time' => time()
                ];
                Db::name('message')->insert($insert_data);

                Db::name('plan')->where(['id' => $plan_id])->update(['is_complete' => 1, 'complete_time' => time()]);

                return true;
            } else {
                Db::name('plan')->where(['id' => $plan_id])->setField('is_complete', -1);

                return false;
            }
        }
    }

    /**
     * AI作答
     * */
    public function aiAnswer()
    {
        $list = Db::name('plan')->field('id,user_id,question_id,prompt')->where(['is_send' => 0, 'is_del' => 0])->order('id asc')->limit(1)->select();
        if ($list) {
            foreach ($list as &$v) {
                $info = Db::name('question')->where(['id' => $v['question_id']])->find();
                $sign = $info['sign'];

                Db::name('plan')->where(['id' => $v['id']])->update(['is_send' => 1, 'send_time' => time()]);

                $this->promptToAi($sign, $v['id'], $v['user_id']);
                sleep(1);
            }
        } else {
            stopPs1();
        }
    }

    public function goAiAnswer()
    {
        // 发起异步请求到长时间任务脚本
        getAiCurl(getHost() . '/index/Ai/aiAnswer');
    }
}
